package com.example.utils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * IP地址获取工具类
 * 支持多种网络环境下的真实IP获取
 */
@Slf4j
@Component
public class IpUtils {

    private static final String[] IP_HEADER_CANDIDATES = {
            "X-Forwarded-For",
            "X-Real-IP", 
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"
    };

    /**
     * 获取客户端真实IP地址
     * 支持代理、负载均衡、CDN等场景
     */
    public String getClientIpAddress(HttpServletRequest request) {
        if (request == null) {
            log.warn("HttpServletRequest为空，返回默认IP");
            return "0.0.0.0";
        }

        // 1. 尝试从各种代理头中获取真实IP
        for (String header : IP_HEADER_CANDIDATES) {
            String ip = request.getHeader(header);
            if (isValidIp(ip)) {
                // 处理多个IP的情况（代理链）
                if (ip.contains(",")) {
                    ip = ip.split(",")[0].trim();
                }
                if (isValidIp(ip)) {
                    log.debug("从头部 {} 获取到IP: {}", header, ip);
                    return ip;
                }
            }
        }

        // 2. 获取请求的远程地址
        String ip = request.getRemoteAddr();
        log.debug("getRemoteAddr获取到IP: {}", ip);

        // 3. 如果是本地地址，尝试获取服务器的外网IP
        if (isLocalIp(ip)) {
            String realIp = getRealServerIp();
            if (realIp != null && !isLocalIp(realIp)) {
                log.info("检测到本地IP {}，使用服务器真实IP: {}", ip, realIp);
                return realIp;
            }
            
            // 4. 如果无法获取外网IP，尝试获取局域网IP
            String lanIp = getLocalAreaNetworkIp();
            if (lanIp != null && !isLocalIp(lanIp)) {
                log.info("使用局域网IP: {}", lanIp);
                return lanIp;
            }
        }

        return ip != null ? ip : "0.0.0.0";
    }

    /**
     * 验证IP地址是否有效
     */
    private boolean isValidIp(String ip) {
        return ip != null 
                && !ip.isEmpty() 
                && !"unknown".equalsIgnoreCase(ip)
                && !"null".equalsIgnoreCase(ip);
    }

    /**
     * 判断是否为本地IP
     */
    private boolean isLocalIp(String ip) {
        if (ip == null || ip.isEmpty()) {
            return true;
        }
        
        return "127.0.0.1".equals(ip) 
                || "localhost".equals(ip)
                || "0:0:0:0:0:0:0:1".equals(ip)
                || "::1".equals(ip);
    }

    /**
     * 获取服务器真实外网IP
     * 适用于云服务器等有公网IP的场景
     */
    private String getRealServerIp() {
        try {
            // 尝试获取所有网络接口
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                
                // 跳过回环接口和虚拟接口
                if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
                    continue;
                }
                
                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    InetAddress inetAddress = inetAddresses.nextElement();
                    
                    // 只处理IPv4地址，排除本地地址
                    if (!inetAddress.isLoopbackAddress() 
                            && !inetAddress.isLinkLocalAddress()
                            && inetAddress.isSiteLocalAddress() == false  // 排除私有IP段
                            && inetAddress.getHostAddress().indexOf(':') == -1) {
                        
                        String ip = inetAddress.getHostAddress();
                        log.debug("找到外网IP: {}", ip);
                        return ip;
                    }
                }
            }
        } catch (SocketException e) {
            log.error("获取服务器真实IP失败", e);
        }
        
        return null;
    }

    /**
     * 获取局域网IP地址
     * 当无法获取外网IP时的备选方案
     */
    private String getLocalAreaNetworkIp() {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                
                // 跳过回环接口和虚拟接口
                if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
                    continue;
                }
                
                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    InetAddress inetAddress = inetAddresses.nextElement();
                    
                    // 获取私有IP段的地址
                    if (!inetAddress.isLoopbackAddress() 
                            && !inetAddress.isLinkLocalAddress()
                            && inetAddress.isSiteLocalAddress()  // 私有IP段
                            && inetAddress.getHostAddress().indexOf(':') == -1) {
                        
                        String ip = inetAddress.getHostAddress();
                        log.debug("找到局域网IP: {}", ip);
                        return ip;
                    }
                }
            }
        } catch (SocketException e) {
            log.error("获取局域网IP失败", e);
        }
        
        return null;
    }

    /**
     * 获取客户端地理位置信息（可扩展）
     * 可以集成第三方IP地址库实现
     */
    public String getIpLocation(String ip) {
        // TODO: 可以集成第三方IP地址库
        if (isLocalIp(ip)) {
            return "本地访问";
        }
        
        // 简单的IP段判断
        if (ip.startsWith("192.168.") || ip.startsWith("10.") || ip.startsWith("172.")) {
            return "内网访问";
        }
        
        return "外网访问";
    }

    /**
     * 记录详细的IP获取日志（调试用）
     */
    public void logIpDetails(HttpServletRequest request) {
        if (!log.isDebugEnabled()) {
            return;
        }
        
        log.debug("=== IP获取详情 ===");
        log.debug("RemoteAddr: {}", request.getRemoteAddr());
        log.debug("RemoteHost: {}", request.getRemoteHost());
        
        for (String header : IP_HEADER_CANDIDATES) {
            String value = request.getHeader(header);
            if (value != null) {
                log.debug("{}: {}", header, value);
            }
        }
        
        log.debug("最终获取IP: {}", getClientIpAddress(request));
        log.debug("================");
    }
} 